// DeviceHooker.h : Defines the class functions for the application.
//

#ifndef __DEVICEHOOKER_H__
#define __DEVICEHOOKER_H__

#include "stdafx.h"
#include "ATASHD3D.h"
#include "HookD3D.h"
#include "Captor.h"
/*
class CDeviceHooker
{
	ULONG m_ulRef;
	CD3dHookDrawPrimitive m_hkrDrawPrimitive;

public:
	CDeviceHooker()
	{
		m_ulRef = 0;
		m_hkrDrawPrimitive = CCaptor::IDirect3DDevice9DrawPrimitive;
	}

	~CDeviceHooker()
	{
		Destroy();
	}

	BOOL Create(IDirect3DDevice9* pDevice)
	{
		m_ulRef++;
		return m_hkrDrawPrimitive.Create(pDevice);
	}

	void Destroy()
	{
		m_hkrDrawPrimitive.Destroy();
	}

	BOOL Hook()
	{
		return m_hkrDrawPrimitive.Hook();
	}
	BOOL UnHook()
	{
		return m_hkrDrawPrimitive.Unhook();
	}

	ULONG AddRef()
	{
		return ++m_ulRef;
	}

	ULONG Release()
	{
		if (!--m_ulRef)
		{
			Destroy();
			return 0;
		}
		return m_ulRef;
	}

	operator IDirect3DDevice9*()
	{
		return m_hkrDrawPrimitive;
	}

	operator CD3dHookDrawPrimitive::PPROC()
	{
		return m_hkrDrawPrimitive;
	}
};
*/
enum HOOKFUNC_DEF
{
	HOOK_DRAWPRIMITIVE9 = 100,
	HOOK_DRAW10,
	HOOK_DRAWINDEXED10
};

class CDeviceHookerBase
{
public:
	virtual ~CDeviceHookerBase(){};
	virtual ULONG AddRef(){return 0;}
	virtual ULONG Release(){return 0;}
	virtual BOOL Hook(){return TRUE;}
	virtual BOOL UnHook(){return TRUE;}
	virtual HOOKFUNC_DEF GetHookerDef(){return HOOK_DRAW10;}
};

template<class T, HOOKFUNC_DEF def>
class CDeviceHooker:public CDeviceHookerBase
{
	ULONG m_ulRef;
	HOOKFUNC_DEF m_funcDef;
	T m_devhooker;

public:
	typedef typename T::PPROC proc_type_p;
	typedef typename T::IFACE_TYPE iface_type;

	CDeviceHooker(proc_type_p newProc)
	{
		m_ulRef = 0;
		m_funcDef = def;
		m_devhooker = newProc;
	}

	virtual ~CDeviceHooker()
	{
		DebugInfoTempA("Destroy device hooker: %x", m_devhooker.IsHooked());
		Destroy();
	}

	BOOL Create(iface_type* pDevice)
	{
		m_ulRef++;
		return m_devhooker.Create(pDevice);
	}

	HOOKFUNC_DEF GetHookerDef()
	{
		return def;
	}

	void Destroy()
	{
		m_devhooker.Destroy();
	}

	virtual BOOL Hook()
	{
		return m_devhooker.Hook();
	}

	virtual BOOL UnHook()
	{
		return m_devhooker.Unhook();
	}

	ULONG AddRef()
	{
		return ++m_ulRef;
	}

	ULONG Release()
	{
		if (!--m_ulRef)
		{
			Destroy();
			return 0;
		}
		return m_ulRef;
	}

	operator iface_type*()
	{
		return m_devhooker;
	}

	operator proc_type_p()
	{
		return m_devhooker;
	}
};

typedef CDeviceHooker<CD3D9HookDrawPrimitive, HOOK_DRAWPRIMITIVE9> CDeviceHookerDrawPrimitive9;
typedef CDeviceHooker<CD3D10HookDraw, HOOK_DRAW10> CDeviceHookerDraw10;
typedef CDeviceHooker<CD3D10HookDrawIndexed, HOOK_DRAWINDEXED10> CDeviceHookerDrawIndexed10;
#endif //__DEVICEHOOKER_H__